const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const WebpackBar = require('webpackbar');
const mapKeys = require('lodash/mapKeys');
const mapValues = require('lodash/mapValues');
const snakeCase = require('lodash/snakeCase');

const getDefaultDllConfig = () => {
  const config = {
    babel: {
      priority: 102,
      packages: ['core-js'],
    },
    vendors: {
      priority: 101,
      packages: ['lodash', 'lodash-decorators', 'axios', 'uuid', 'numeral'],
    },
    common: {
      priority: 100,
      packages: [
        // 'core-js/stable',
        // 'regenerator-runtime/runtime',
        'react',
        'react-dom',
        'react-intl-universal',
        'cropperjs',
        'dva',
        'react-cropper',
        // 'vue',
        'cpaas-ui',
        'choerodon-ui',
        'choerodon-ui/pro',
        // '@cpaas-front-ui/cfg',
      ],
    },
    vendorsGraph: {
      packages: ['echarts'],
    },
  };

  if (process.env.MULTIPLE_SKIN_ENABLE === 'true') {
    config.common.packages.push('@cpaas-front-ui/cfg');
  }

  config.vue = {
    packages: ['vue'],
  };
  return config;
};

const getOriginDllConfig = (_config) => {
  const paths = require('./paths');
  const cpaasConfig = paths.getCpaasBootConfig(paths.appPath) || {};
  let config = {};
  if (cpaasConfig.dllConfig) {
    config = cpaasConfig.dllConfig;
  } else {
    config = getDefaultDllConfig();
  }
  config = mapValues(config, (value, key) => {
    return {
      ...value,
      priority: value.priority || 0,
    };
  });

  return config;
};

const getDllConfig = () => {
  let config = getOriginDllConfig();
  config = mapKeys(config, (value, key) => {
    return snakeCase(key);
  });
  config = mapValues(config, (value, key) => {
    return value.packages;
  });
  return config;
};

const getDllPluginConfig = () => {
  const paths = require('./paths');
  const dllPlugins = Object.entries(getOriginDllConfig())
    .sort((a, b) => a[1].priority - b[1].priority)
    .map((item) => snakeCase(item[0]))
    .map(
      (key) =>
        new webpack.DllReferencePlugin({
          context: paths.appRootPath,
          manifest: require(path.resolve(paths.appDll, `${key}.manifest.json`)),
        })
    );

  return dllPlugins;
};

module.exports = function () {
  const paths = require('./paths');
  require('./env');
  const cpaasConfig = paths.getCpaasBootConfig(paths.appPath) || {};
  const theme = require('./base/getTheme')();

  const FORCE_ENABLE_POLYFILL = process.env.FORCE_ENABLE_POLYFILL === 'true';

  const dllConfig = getDllConfig({
    paths,
  });
  let config = {
    mode: 'production',
    performance: {
      hints: false,
    },
    output: {
      path: paths.appDll,
      publicPath: paths.servedPath,
      filename: '[name].[hash].dll.js',
      library: '[name]_[hash]',
    },
    entry: dllConfig,
    module: {
      strictExportPresence: true,
      rules: [
        {
          test: [/\.d\.ts$/],
          use: require.resolve('null-loader'),
        },
        {
          test: [
            /\.bmp$/,
            /\.gif$/,
            /\.jpe?g$/,
            /\.png$/,
            /\.eot$/,
            /\.woff$/,
            /\.ttf$/,
            /\.svg$/,
          ],
          loader: require.resolve('url-loader'),
          options: {
            limit: 10000,
            name: 'static/media/[name].[hash:8].[ext]',
          },
        },
        {
          test: /\.css$/,
          use: [
            {
              loader: require.resolve('style-loader'),
              options: {
                insert: function insertAtTop(element) {
                  var parent = document.querySelector('head');
                  parent.insertBefore(element, parent.firstChild);
                },
              },
            },
            {
              loader: 'css-loader',
              options: {
                importLoaders: 1,
              },
            },
          ],
        },
        {
          test: /\.less$/,
          use: [
            {
              loader: require.resolve('style-loader'),
              options: {
                insert: function insertAtTop(element) {
                  var parent = document.querySelector('head');
                  parent.insertBefore(element, parent.firstChild);
                },
              },
            },
            {
              loader: 'css-loader',
              options: {
                importLoaders: 1,
              },
            },
            {
              loader: 'less-loader',
              options: {
                modifyVars: theme,
                javascriptEnabled: true,
              },
            },
          ],
        },
        // {
        //   // IE 兼容性处理， 会读取 cwd 目录的 package.json["browserslist"]
        //   test: /\/(vue|@vue|vue-.*)\/.*\.(js|mjs|jsx|ts|tsx)$/,
        //   use: {
        //     loader: 'babel-loader',
        //     options: {
        //       babelrc: false,
        //       presets: [
        //         ['react-app', { absoluteRuntime: false }],
        //       ],
        //     },
        //     // options: require('./base/getBabelrc')(),
        //   },
        // },
        {
          // IE 兼容性处理， 会读取 cwd 目录的 package.json["browserslist"]
          // quill-image-drop-and-paste 需要特殊处理， 因为dll文件会有不兼容ie11 的写法
          test: FORCE_ENABLE_POLYFILL
            ? /\.(js|mjs|jsx|ts|tsx)$/
            : /\/(quill-image-drop-and-paste)\/.*\.(js|mjs|jsx|ts|tsx)$/,
          use: {
            loader: 'babel-loader',
            options: {
              babelrc: false,
              presets: [['react-app', { absoluteRuntime: false }]],
            },
            // options: require('./base/getBabelrc')(),
          },
        },
      ],
    },
    resolve: {
      alias: require('./base/getAlias')(),
      modules: [
        'node_modules',
        'node_modules/cpaas-front/node_modules',
        'node_modules/cpaas-boot/node_modules',
      ],
    },
    plugins: [
      new CleanWebpackPlugin({
        root: paths.appRootPath, // 根目录
        verbose: true, // 开启在控制台输出信息
        dry: false, // 启用删除文件
      }),
      new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
      new FriendlyErrorsWebpackPlugin(),
      new WebpackBar({ name: '🚚  CPaas Front Dll', color: '#29BECE' }),
      new webpack.DllPlugin({
        path: path.resolve(paths.appDll, '[name].manifest.json'),
        name: '[name]_[hash]',
        context: paths.appRootPath,
      }),
    ],
  };

  if (cpaasConfig.webpackConfig) {
    config = cpaasConfig.webpackConfig(config, 'dll');
  }

  return config;
};

module.exports.getDllConfig = getDllConfig;
module.exports.getDllPluginConfig = getDllPluginConfig;
